package sql_models

import (
	"fmt"

	"gorm.io/gorm"
)

type Device struct {
	ID     uint    `gorm:"primaryKey"`
	SN     string  `gorm:"size:100;not null;unique"` // 设备SN码，必须唯一
	ShopID *string `gorm:"size:100;index"`           // 关联的店铺ID，允许为 NULL
	RoomID *string `gorm:"size:50;index"`            // 关联的房间ID，允许为 NULL
	Shop   Shop    `gorm:"foreignKey:ShopID"`
	Room   Room    `gorm:"foreignKey:RoomID;references:RoomID"`
}

// RegisterDevice 注册设备，写入SN到数据库
func RegisterDevice(sn string) error {
	var device Device
	// 检查设备是否已经存在
	err := DB.Where("sn = ?", sn).First(&device).Error
	if err == gorm.ErrRecordNotFound {
		// 如果设备不存在，则创建新的设备
		device = Device{
			SN:     sn,
			ShopID: nil, // 初始没有关联 shop，设置为 NULL
			RoomID: nil, // 初始没有关联 room，设置为 NULL
		}
		if err := DB.Create(&device).Error; err != nil {
			return err
		}
		fmt.Printf("设备 %s 成功注册\n", sn)
		return nil
	} else if err != nil {
		// 查询出现错误
		return err
	} else {
		// 设备已经存在
		return fmt.Errorf("设备 %s 已经存在", sn)
	}
}

// DeleteDevice 删除设备，取消所有关联并从数据库中删除
func DeleteDevice(sn string) error {
	var device Device
	// 查找设备是否存在
	err := DB.Where("sn = ?", sn).First(&device).Error
	if err == gorm.ErrRecordNotFound {
		return fmt.Errorf("设备 %s 未找到", sn)
	} else if err != nil {
		return err
	}

	// 删除设备前，确保取消与 shop 和 room 的关联
	device.ShopID = nil
	device.RoomID = nil
	if err := DB.Save(&device).Error; err != nil {
		return err
	}

	// 从数据库中删除设备
	if err := DB.Delete(&device).Error; err != nil {
		return err
	}

	fmt.Printf("设备 %s 已删除\n", sn)
	return nil
}

// AssociateDeviceWithShop 仅关联设备到指定的 shop
func AssociateDeviceWithShop(sn string, shopID string) error {
	var device Device
	// 查找设备是否存在
	err := DB.Where("sn = ?", sn).First(&device).Error
	if err == gorm.ErrRecordNotFound {
		return fmt.Errorf("设备 %s 未注册", sn) // 确保设备已注册
	} else if err != nil {
		return err
	}

	// 更新设备的 shopID
	device.ShopID = &shopID
	device.RoomID = nil // 清除之前关联的 room
	if err := DB.Save(&device).Error; err != nil {
		return err
	}

	fmt.Printf("设备 %s 成功关联到 ShopID: %s\n", sn, shopID)
	return nil
}

// UnassociateDeviceWithShop 取消设备与 shop 的关联，并自动取消 room 的关联
func UnassociateDeviceWithShop(sn string) error {
	var device Device
	// 查找设备是否存在
	err := DB.Where("sn = ?", sn).First(&device).Error
	if err == gorm.ErrRecordNotFound {
		return fmt.Errorf("设备 %s 未注册", sn)
	} else if err != nil {
		return err
	}

	// 取消与 shop 和 room 的关联
	device.ShopID = nil
	device.RoomID = nil
	if err := DB.Save(&device).Error; err != nil {
		return err
	}

	fmt.Printf("设备 %s 成功取消关联 shop 和 room\n", sn)
	return nil
}

// AssociateDeviceWithRoom 仅在设备已关联 shop 时关联 room，同时检查 room 是否已被其他设备绑定
func AssociateDeviceWithRoom(sn string, roomID string) error {
	var device Device
	// 查找设备是否存在
	err := DB.Where("sn = ?", sn).First(&device).Error
	if err == gorm.ErrRecordNotFound {
		return fmt.Errorf("设备 %s 未注册", sn)
	} else if err != nil {
		return err
	}

	// 确保设备已经关联 shop 才能关联 room
	if device.ShopID == nil {
		return fmt.Errorf("设备 %s 尚未关联 shop，无法关联 room", sn)
	}

	// 检查是否有其他设备已经绑定该 room
	var existingDevice Device
	err = DB.Where("room_id = ?", roomID).First(&existingDevice).Error
	if err == nil {
		return fmt.Errorf("房间 %s 已经被设备 %s 绑定", roomID, existingDevice.SN)
	} else if err != gorm.ErrRecordNotFound {
		return err // 其他数据库错误
	}

	// 更新设备的 roomID
	device.RoomID = &roomID
	if err := DB.Save(&device).Error; err != nil {
		return err
	}

	fmt.Printf("设备 %s 成功关联到 RoomID: %s\n", sn, roomID)
	return nil
}

// UnassociateDeviceWithRoom 仅取消设备与 room 的关联，保留 shop 的关联
func UnassociateDeviceWithRoom(sn string) error {
	var device Device
	// 查找设备是否存在
	err := DB.Where("sn = ?", sn).First(&device).Error
	if err == gorm.ErrRecordNotFound {
		return fmt.Errorf("设备 %s 未注册", sn)
	} else if err != nil {
		return err
	}

	// 确保设备已经关联 shop，才能取消 room 的关联
	if device.ShopID == nil {
		return fmt.Errorf("设备 %s 未关联 shop，无法取消 room 关联", sn)
	}

	// 更新 roomID 为 nil，保留 shop 关联
	device.RoomID = nil
	if err := DB.Save(&device).Error; err != nil {
		return err
	}

	fmt.Printf("设备 %s 成功取消 room 关联\n", sn)
	return nil
}

// GetDeviceBySN 根据SN获取设备
func GetDeviceBySN(sn string) (*Device, error) {
	var device Device
	err := DB.Where("sn = ?", sn).First(&device).Error
	if err != nil {
		return nil, err
	}
	return &device, nil
}

// GetShopAndRooms 获取Shop和其关联的Rooms
func GetShopAndRooms(shopID string) (*Shop, []Room, error) {
	var shop Shop
	var rooms []Room

	err := DB.First(&shop, "id = ?", shopID).Error
	if err != nil {
		return nil, nil, err
	}

	err = DB.Where("shop_id = ?", shopID).Find(&rooms).Error
	if err != nil {
		return nil, nil, err
	}

	return &shop, rooms, nil
}
